﻿// (c) Copyright Fernando Cerqueira.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;

// ReSharper disable CheckNamespace
namespace DevPhone.Controls
// ReSharper restore CheckNamespace
{
    /// <summary>
    /// Displays the list of items and allows single or multiple selection.
    /// </summary>
    [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
    public partial class CheckPickerPage : PhoneApplicationPage
    {
        private const string StateKeyValue = "CheckPickerPageStateValue";
        private const string ExternalAddress = "app://external/";

        /// <summary>
        /// Gets or sets the head page.
        /// </summary>
        public object HeaderContent { get; set; }

        /// <summary>
        /// Gets or sets the list of items to display.
        /// </summary>
        public IList Items { get;  private set; }

        /// <summary>
        /// Gets or sets the selected item.
        /// </summary>
        public IList SelectedItems { get; internal set; }

        /// <summary>
        /// Gets or sets the item template
        /// </summary>
        public DataTemplate PageHeaderTemplate { get; set; }

        public bool AppBarPageCheckOptions { get; set; }

        /// <summary>
        /// Gets or sets the DataContext header template
        /// </summary>
        public object PageHeaderDataContext { get; set; }

        /// <summary>
        /// Gets or sets the image Background
        /// </summary>
        public ImageBrush PageImageBackground { get; set; }

        /// <summary>
        /// Gets or sets the page Background
        /// </summary>
        public Brush PageBackground { get; set; }

        /// <summary>
        /// Gets or sets the item template
        /// </summary>
        public DataTemplate PageItemTemplate { get; set; }

        /// <summary>
        /// Creates a list picker page.
        /// </summary>
        public CheckPickerPage()
        {
            InitializeComponent();
            Items = new List<object>();
            SelectedItems = new List<object>();
            Loaded += OnLoaded;
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            Picker.Opacity = 1;
            foreach (object obj in ApplicationBar.Buttons)
            {
                var button = obj as IApplicationBarIconButton;
                if (null != button)
                {
                    if ("DONE" == button.Text)
                    {
                        button.Text = LocalizedResources.ControlResources.AppBar_Done;
                        button.Click += OnDoneButtonClick;
                    }
                    else if ("CANCEL" == button.Text)
                    {
                        button.Text = LocalizedResources.ControlResources.AppBar_Cancel;
                        button.Click += OnCancelButtonClick;
                    }
                    else if ("CHECKALL" == button.Text)
                    {
                        button.Text = LocalizedResources.ControlResources.AppBar_CheckAll;
                        button.Click += OnCheckAllButtonClick;
                        button.IsEnabled = AppBarPageCheckOptions;
                    }
                    else if ("UNCHECKALL" == button.Text)
                    {
                        button.Text = LocalizedResources.ControlResources.AppBar_UncheckAll;
                        button.Click += OnUncheckAllButtonClick;
                        button.IsEnabled = AppBarPageCheckOptions;
                    }
                }
            }

        }

        /// <summary>
        /// Called when a page becomes the active page in a frame.
        /// </summary>
        /// <param name="e">An object that contains the event data.</param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            if (null == e)
            {
                throw new ArgumentNullException("e");
            }

            base.OnNavigatedTo(e);

            // Restore Value if returning to application (to avoid inconsistent state)
            if (State.ContainsKey(StateKeyValue))
            {
                State.Remove(StateKeyValue);

                // Back out from picker page for consistency with behavior of core pickers in this scenario
                if (NavigationService.CanGoBack)
                {
                    NavigationService.GoBack();
                    return;
                }
            }

            Picker.DataContext = Items;

            if (PageHeaderTemplate != null)
            {
                HeaderTitle.Margin = new Thickness(0);
                HeaderTitle.DataContext = PageHeaderDataContext;
            }
            HeaderTitle.Content = HeaderContent;
            HeaderTitle.ContentTemplate = PageHeaderTemplate;

            MainGrid.Background = PageImageBackground ?? PageBackground;


            Picker.SelectionMode = SelectionMode.Multiple;

            if (null != PageItemTemplate)
            {
                Picker.ItemTemplate = PageItemTemplate;
            }

            foreach (object item in Items)
            {
                if (null != SelectedItems && SelectedItems.Contains(item))
                {
                    Picker.SelectedItems.Add(item);
                }
            }
        }

        private void OnCheckAllButtonClick(object sender, EventArgs e)
        {
            Picker.SelectedItems.Clear();
            foreach (object item in Items)
            {
                Picker.SelectedItems.Add(item);
            }
        }

        private void OnUncheckAllButtonClick(object sender, EventArgs e)
        {
            Picker.SelectedItems.Clear();
        }

        private void OnDoneButtonClick(object sender, EventArgs e)
        {
            // Commit the value and close
            SelectedItems = Picker.SelectedItems;
            ClosePickerPage();
        }

        private void OnCancelButtonClick(object sender, EventArgs e)
        {
            // Close without committing a value
            SelectedItems = null;
            ClosePickerPage();
        }


        /// <summary>
        /// Called when the Back key is pressed.
        /// </summary>
        /// <param name="e">Event arguments.</param>
        protected override void OnBackKeyPress(CancelEventArgs e)
        {
            if (null == e)
            {
                throw new ArgumentNullException("e");
            }
            // Cancel back action so we can play the Close state animation (then go back)
            e.Cancel = true;
            SelectedItems = null;
            ClosePickerPage();
        }

        private void ClosePickerPage()
        {
            // Prevent user from selecting an item as the picker is closing,
            // disabling the control would cause the UI to change so instead
            // it's hidden from hittesting.
            Picker.IsHitTestVisible = false;
            if (NavigationService.CanGoBack)
            {
                NavigationService.GoBack();
            }
        }

        /// <summary>
        /// Called when a page is no longer the active page in a frame.
        /// </summary>
        /// <param name="e">An object that contains the event data.</param>
        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            if (null == e)
            {
                throw new ArgumentNullException("e");
            }

            base.OnNavigatedFrom(e);

            // Save Value if navigating away from application
            if (ExternalAddress == e.Uri.ToString())
            {
                State[StateKeyValue] = StateKeyValue;
            }
        }
    }
}